/*!
 * Copyright (c) 2010 Jacob Essex
 *
 * Dual licenced under MIT or GPL 3 licneces
 * 
 * See the GPL3 or MIT files in the main directory for details
 */

/**
 * The idea of this class is to abstract as much as possible of the SO spesific HTML away
 * from the application so that if SO decides to change the HTML in any way it is easy to fix
 */

require.def('se/site', ['config', 'lib/hashstring', 'db', 'db/sites', 'lib/jquery'],
function(Config, Hashstring, Db, Sites){
    var NO_USER = 0;

    /**
     * Injects HTML into the page
     *
     * @param usr the user id
     * @param url the url of the page to be added. This must be a page from the extension
     * @param the callback that acutally adds the data. This should accept a single
     *              parameter, the html to add to the page.
     *              the callback function should do the work adding it to the page
     */
    var injectHtml = function(usr, url, callback){
            var req = {
                obj:'site',
                db: Config.SettingsDb
            }

            req.func = 'getByHost';
            req.args = [window.location.host];

            chrome.extension.sendRequest(req, function(site){
                //todo not required, but it may be good to check if require.js has already been added
                var head= document.getElementsByTagName('head')[0];
                var script= document.createElement('script');
                script.type= 'text/javascript';
                script.src = chrome.extension.getURL('lib/require.js');


                script.onload = function(){
                   var script= document.createElement('script');
                   //base url for require.js and site information so that the added code can access some
                   //basic stuff with ease
                   script.innerHTML = 'require({baseUrl:\'' + chrome.extension.getURL('') + '\'});'
                                    + 'var SiteInformation = {'
                                    + ' IsActive:'+site.IsActive+','
                                    + ' ApiUrl:\''+ site.ApiUrl +'\','
                                    + ' UserId:\'' + usr + '\''
                                    + '};'
                   $('body').append(script);

                   chrome.extension.sendRequest({obj:'ajax', 'url':url}, function(html){
                       callback(html);
                      });
                }
                head.appendChild(script);
            });
    };

    return {
        'NO_USER': NO_USER,
        Site: function(context) {
            context = context ? context : window.document;


            var that = this;

            var uniqueId = (function() {
               var id = 0; 
               return function() { return id++; };
            })(); 


            var getTabId = function(name){
                return name.replace(/[^a-zA-Z]/, '');
            }

            /**
             * Abstract class for a page. 
             *
             * @param Regex that should match all the urls that this page applies to
             */
            function Page(path, urlMatch){
                var that = this;

                /**
                 * Returns true if the user is on a page to which this page object aplies
                 */
                this.isOnPage = function(){
                    var loc = window.location.href;
                    var i = loc.indexOf(window.location.host) + window.location.host.length;
                    var path = loc.substr(i); //loc is just the path, including the /
                    var re = new RegExp(urlMatch);
                    return re.test(path);
                }

                /**
                 * Adds a tab. This is fairly generic as most pages support adding tabs
                 * 
                 * This uses the callback function onTabClick that should be added to
                 * all classes inheriting from this class. The function accepts takes an
                 * input of the tag button and the url of the page to load. It is the functions
                 * responsibility to ensure that the content from the loaded url is displayed
                 * properly
                 *
                 * TODO consider passing the content rather than the url?
                 *
                 * @param title this is the lable that is given to the tag
                 * @param url this is the url of the page to load when the tag is active
                 *              the url is loaded via ajax, so it cannot use the extension 
                 *              spesific features.
                 */
                this.addTab = function(title, url){
                    if ( !that.isOnPage() ) return;
                    var id = getTabId(title);//'addedtab'// encodeURIComponent(title);

                    $('#tabs', context).append('<a id="' + id + '">'+title+'</a>')
                    var e = $('#tabs #'+id, context); //the tag we just added
    
                    //if we don't do this, when you click on the tab you origanally
                    //loaded the page on, nothing will happen
                    $('#tabs .youarehere').click(function(){
                        window.location.hash = 'tab-top';
                        window.location.reload();
                    }).attr('href', 'javascript:void(0)'); 
                    
                    e.click(function(){
                        Hashstring.set('tab', title);
                        $('#tabs a', context).removeClass('youarehere');
                        e.addClass('youarehere');
                        that.onTabClick(e, url);
                    });
                }

                this.gotoTab = function(name){
                    var id = getTabId(name);//name encodeURIComponent(name);
                    window.location = 'http://' + window.location.host + '/' + path + '#tab=' + id
                }
            }

            this.runTabCheck = function(){
                if ( Hashstring.contains('tab') ){
                    var id = getTabId(Hashstring.get('tab'));
                    $('#'+id).click();
                }
            }

            /**
             * Trying to stick to the SO naming scheme here. A module is a section of HTML/code that
             * apears down the side of some sections
             */
            function Module(){
            }

            this.user = function(){
                var elm = $('#hlinks-user', context)
                if ( elm.length == 0 ){
                    return NO_USER;
                }else{
                    var href = $(elm).find('a:first').attr('href'); //get the url behind the username link
                    return href !== undefined ? href.replace(/[^0-9]/g, '') : NO_USER; //stripping everything but numbers should give us the user id
                }
            }

            //todo this assumes the stylesheet is first. not a good thing
            this.css = function(){
                return $('link').attr('href');
            }

            /**
             * Adds a notification exactly the same as you get when for example you get a new badge
             *
             * @param text the text of the notification. It can include a link.
             * @param linkClicked the function to call if the user clicked the link
             * @param closeClicked the function to call if the user closed the notification
             */
            this.addNotification = function(text, funcs){
                var id = 'stakodd-notification-'+uniqueId();
                $('#notify-container', context).append('	<div id="'+id+'">'
                                              +  '		<span class="notify-close">'
                                              +			'<a class="oddsclose" title="dismiss this notification">×</a>'
                                              +		'</span>'
                                              +		text
                                              +	'</div>');
                var hide = function(){
                    $('#' + id, context).remove();
                }
                $('#'+id+' a[class!=oddsclose]', context).click(function(){
                    hide();
                    funcs.yes();
                });
                $('#'+id+' span', context).click(function(){
                    hide();
                    funcs.no();
                });
            }

            /**
             * Class that deals with the unanswered page
             */
            this.unanswered = new Page('unanswered', '^/unanswered');
            this.unanswered.onTabClick = function(e, url){
                $('.page-sizer').html('');
                $('.pager').html('');
                injectHtml(that.user(), url, function(html){
                    $('#questions', context).html(html);
                });
            };


            this.questions = new Page('questions', '^/questions[^/]*$');
            this.questions.onTabClick = this.unanswered.onTabClick;

            /**
             * Class deals with options page
             */
            this.options = new Page('users/' + this.user() + '/', '^/users/[0-9]+');
            this.options.onTabClick = function(e, url){
                var index = $('.subheader:has(#tabs)', context).index();

                $('#mainbar-full', context).children().each(function(){
                    var e = $(this);
                    if ( e.index() > index ){
                        $(this).hide();
                    }
                });
                injectHtml(that.user(), url, function(html){
                    $('#mainbar-full', context).append(html);
                });
            };



        }
    }
});
